/**
 * 
 */
package org.stars.util.jar;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.regex.Pattern;

import org.stars.util.StringUtility;

/**
 * Classe di utilità per recuperare
 * 
 * @author Francesco Benincasa (908099)
 * @date 07/nov/07, 19:09:08
 * 
 */
public class JarResourceUtility {

	/**
	 * pezzo di regular expression da aggiungere al matcher
	 */
	protected final static String regEx = "([^\\\\]*)";

	/**
	 * Unisce il pattern da applicare al nome della directory e del file e ne
	 * ottiene uno solo.
	 * 
	 * @param sDirPattern
	 *            pattern da applicare al nome delle directory
	 * @param sFilePattern
	 *            pattern da applicare al nome del file
	 * @return pattern da applicare al nome della risorsa
	 */
	protected static String buildJarResourcePattern(String sDirPattern,
			String sFilePattern) {
		String ret;
									
		sDirPattern = StringUtility.nvl(sDirPattern, "*").toLowerCase();
		sDirPattern = StringUtility.replace(sDirPattern, "*", regEx);
		sDirPattern = StringUtility.replace(sDirPattern, ".", "\\.");		

		sFilePattern = StringUtility.nvl(sFilePattern, "*").toLowerCase();
		sFilePattern = StringUtility.replace(sFilePattern, "*", regEx);
		sFilePattern = StringUtility.replace(sFilePattern, ".", "\\.");

		ret = sDirPattern + "/" + sFilePattern;
		return ret;
	}

	/**
	 * @param sJarPattern
	 * @param sDirectoryPattern
	 * @param sFilePattern
	 */
	public static void findResources(String sJarPattern,
			String sDirectoryPattern, String sFilePattern) throws Exception {
		findResources(sJarPattern, sDirectoryPattern, sFilePattern, null);
	}

	/**
	 * Recupera l'intero elenco dei jar che entrano nel classpath attualmente
	 * impiegato.
	 * 
	 * @param sJarPattern
	 *            pattern da applicare al nome del jar.
	 * @param sDirectoryPattern
	 *            pattern da applicare alla directory delle risorse
	 * @param sFilePattern
	 *            pattern da applicare al nome dei file.
	 * @param jarResourceHandler
	 * @throws Exception 
	 * 
	 */
	public static void findResources(String sJarPattern,
			String sDirectoryPattern, String sFilePattern,
			FoundJarResourceEventHandler jarResourceHandler) throws Exception {

		if (jarResourceHandler == null) {
			jarResourceHandler = new JarResourceDefaultEventHandler();
		}

		Pattern resourcePattern = Pattern.compile(buildJarResourcePattern(
				sDirectoryPattern, sFilePattern), Pattern.MULTILINE
				| Pattern.CASE_INSENSITIVE);

		ArrayList<String> jars = JarUtility.getListOfJar(sJarPattern);
		JarFile jarFile = null;
		int n=0;
		String name, fullName, path;		

		for (String location : jars) {
			
			try {
				jarFile = new JarFile(location);
				JarEntry entry; 
				
				// set name of jar
				jarResourceHandler.setJarName(jarFile.getName());
				
				InputStream resourceInputStream = null;

				Enumeration<JarEntry> lista = jarFile.entries();
				while (lista.hasMoreElements()) {
					entry = lista.nextElement();

					if (!entry.isDirectory()
							&& resourcePattern.matcher(entry.getName()).find()) {

						try {
							resourceInputStream = jarFile.getInputStream(entry);

							fullName=entry.getName();							
							n=fullName.lastIndexOf("/");
							path=entry.getName().substring(0,n+1);
							name=entry.getName().substring(n+1);
							
							jarResourceHandler.onFoundResourceEvent(path, name, resourceInputStream);
						} finally {
							try {
								resourceInputStream.close();
								
							} catch (Exception a1) {
								System.out.println("Errore"+a1.toString());
							}
						}

					}
				}
			} catch (IOException ioe) {
				/*
				 * System.out.println("Could not search jar file '"+ location+ "'
				 * for implementations of "+ parentType.getName()+ "due to an
				 * IOException: "+ ioe.getMessage());
				 */
			} finally {
				try {
					if (jarFile != null) {
						jarFile.close();
					}
				} catch (IOException e) {

				}
			}
		}

		return;
	}
}
